package sf.dsl.example;

import sf.database.dialect.DBDialect;
import sf.database.jdbc.sql.SQLParameter;

import java.io.Serializable;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;

/**
 * com.querydsl.core.types.OrderSpecifier
 */
public class OrderField implements IField, Serializable {

    private final Order order;

    private final SimpleField target;

    private final OrderNull orderNull;

    public enum OrderNull {
        NullsFirst,
        NullsLast
    }

    public OrderField(SimpleField target, Order order, OrderNull orderNull) {
        this.target = target;
        this.order = order;
        this.orderNull = orderNull;
    }

    public OrderField(SimpleField target, Order order) {
        this(target, order, null);
    }

    /**
     * Get the order of this specifier
     * @return order
     */
    public Order getOrder() {
        return order;
    }

    /**
     * Get whether the order is ascending or not
     * @return ascending order
     */
    public boolean isAscending() {
        return order == Order.ASC;
    }

    /**
     * Get the target expression of this OrderSpecifier
     * @return target expression
     */
    public SimpleField getTarget() {
        return target;
    }

    /**
     * Get the null handling
     * @return null handling
     */
    public OrderNull getNullHandling() {
        return orderNull;
    }

    /**
     * Create a new OrderSpecifier instance with null first enabled
     * @return new instance with null first enabled
     */
    public OrderField nullsFirst() {
        return new OrderField(target, order, OrderNull.NullsFirst);
    }

    /**
     * Create a new OrderSpecifier instance with nulls last enabled
     * @return new instance with nulls last enabled
     */
    public OrderField nullsLast() {
        return new OrderField(target, order, OrderNull.NullsLast);
    }

    @Override
    public void toConditionSql(StringBuilder sb, List<SQLParameter> list, AtomicBoolean useDefaultTableNameAlias, boolean useTablePrefix, DBDialect dialect) {
        target.toConditionSql(sb, list, useDefaultTableNameAlias, useTablePrefix, dialect);
        sb.append(" ").append(order.name());
        if (orderNull != null) {
            switch (orderNull) {
                case NullsFirst:
                    sb.append(" nulls first");
                    break;
                case NullsLast:
                    sb.append(" nulls last");
                    break;
                default:
                    break;
            }
        }
    }

    @Override
    public void toSelectSql(StringBuilder sb, List<SQLParameter> list, AtomicBoolean useDefaultTableNameAlias, DBDialect dialect) {

    }

    @Override
    public String toString() {
        return target + " " + order;
    }

    @Override
    public boolean equals(Object o) {
        if (o == this) {
            return true;
        } else if (o instanceof OrderField) {
            OrderField os = (OrderField) o;
            return os.order.equals(order) && os.target.equals(target)
                    && os.orderNull.equals(orderNull);
        } else {
            return false;
        }
    }

    @Override
    public int hashCode() {
        return target.hashCode();
    }

}
